package com.zmn.plat.dubbo.impl.orderconfig.orderstock;

import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.manager.common.database.annotation.ReadOnlyConnection;
import com.zmn.plat.business.interfaces.channel.ChannelServiceCategoryBService;
import com.zmn.plat.business.interfaces.product.ProductBService;
import com.zmn.plat.common.constant.ChannelConsts;
import com.zmn.plat.common.constant.ProductConsts;
import com.zmn.plat.common.dictionary.PlatErrorCodeDict;
import com.zmn.plat.common.dto.product.ProductAllMsgInfoDRO;
import com.zmn.plat.common.dto.product.ProductDIO;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.dubbo.interfaces.orderconfig.orderstock.ChannelOrderStockListRemoteService;
import com.zmn.plat.dubbo.utils.DubboConsts;
import com.zmn.plat.model.entity.orderconfig.orderstock.channel.ChannelConfigClose;
import com.zmn.plat.model.entity.orderconfig.orderstock.channel.ChannelConfigCloseQuery;
import com.zmn.plat.services.interfaces.orderconfig.oderstock.channel.ChannelConfigCloseService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述：订单库存dubbo接口类
 *
 * @author: tanghongjun
 * @time: 2020/4/21 9:40
 */
@Service(version = DubboConsts.INTERFACE_VERSION, validation = "true")
@Slf4j
public class ChannelOrderStockListRemoteServiceImpl implements ChannelOrderStockListRemoteService {

    @Resource
    ChannelConfigCloseService channelConfigCloseService;
    @Autowired
    ProductBService productBService;
    @Resource
    ChannelServiceCategoryBService channelServiceCategoryBService;

    @Override
    @ReadOnlyConnection
    @Cacheable(cacheNames = "redis5m", key = "'orderstock:channel:stock:channel:'+#p0+':date:'+#p1+':serv:'+#p2+':categ:'+#p3", unless = "#result.status != 200")
    public ResponseDTO<String> checkChannelOrderStockStatusByChannelIdAndDateAndCateg(Integer channelId, Date date, Integer servCategId, Integer categId) {
        log.info("checkChannelOrderStockStatusByChannelIdAndDateAndCateg 参数为 channelId:{},date:{},servCategId:{},categID:{}", channelId, date, servCategId, categId);
        if (Objects.isNull(channelId) || Objects.isNull(servCategId) || Objects.isNull(categId) || Objects.isNull(date)) {
            return ResponseDTO.fromErrorCodeTable(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        if (Arrays.asList(ChannelConsts.ORDER_STOCK_SPECIAL_CHANNEL).contains(channelId)) {
            return ResponseDTO.success("unlimited");
        }

        // 渠道是否开通分类，没开通取上级渠道id
        try {
            channelId = channelServiceCategoryBService.getAvailableCategoryChannelId(channelId);
        } catch (PlatException e) {
            return ResponseDTO.fromErrorCodeTable(e.getErrorCode());
        }

        List<ChannelConfigClose> channelConfigCloses = listByChannelConfigCloseQuery(channelId, date, servCategId, categId);
        return ResponseDTO.success(CollectionUtil.isNotNullOrEmpty(channelConfigCloses) ? "true" : "false");
    }


    @Override
    @ReadOnlyConnection
    @Cacheable(cacheNames = "redis5m", key = "'orderstock:channel:stock:channel:'+#p0+':date:'+#p1+':product:'+#p2", unless = "#result.status != 200")
    public ResponseDTO<String> checkChannelOrderStockStatusByChannelIdAndDateAndShowProductId(Integer channelId, Date date, Integer showProductId) {
        log.info("checkChannelOrderStockStatusByChannelIdAndDateAndShowProductId 参数为 channelId:{},date:{},showProductId:{}", channelId, date, showProductId);

        try {
            if (Objects.isNull(channelId) || Objects.isNull(showProductId) || Objects.isNull(date)) {
                return ResponseDTO.fromErrorCodeTable(PlatErrorCodeDict.ERROR_CODE_RESULT_NULL);
            }

            if (Arrays.asList(ChannelConsts.ORDER_STOCK_SPECIAL_CHANNEL).contains(channelId)) {
                return ResponseDTO.success("unlimited");
            }

            ProductDIO productDIO = new ProductDIO();
            productDIO.setProductId(showProductId);
            productDIO.setStatus(GlobalConsts.YES);
            List<ProductAllMsgInfoDRO> productAllMsgInfoDROList = productBService.listByDIO(productDIO); // 巨坑啊！！！为啥去查这个接口？？？ 待优化
            if (CollectionUtils.isEmpty(productAllMsgInfoDROList)) {
                log.info("产品不存在或状态有误.errorCode:{}", PlatErrorCodeDict.ERROR_CODE_ORDERCONFIG_PRODUCT_NOT_VALIABLE);
                return ResponseDTO.fromErrorCodeTable(PlatErrorCodeDict.ERROR_CODE_ORDERCONFIG_PRODUCT_NOT_VALIABLE);
            }

            ProductAllMsgInfoDRO product = productAllMsgInfoDROList.get(0);

            return checkChannelOrderStockStatusByChannelIdAndDateAndCateg(channelId, date, product.getProductBaseDRO().getServCategId(), product.getProductBaseDRO().getCategId());
        } catch (PlatException ex) {
            return ResponseDTO.fromErrorCodeTable(ex.getErrorCode());
        } catch (Exception e) {
            log.error("checkChannelOrderStockStatusByChannelIdAndDateAndShowProductId error.channelId:{},date:{},showProductId:{}", channelId, date, showProductId, e);
            return ResponseDTO.fail(GlobalConsts.FAILD_MSG);
        }
    }

    @Override
    @ReadOnlyConnection
    @Cacheable(cacheNames = "redis5m", key = "'orderstock:channel:stock:channel:'+#p0+':days:'+#p1+':serv:'+#p2+':categ:'+#p3", unless = "#result.status != 200")
    public ResponseDTO<List<Date>> listChannelOrderStockStatusByChannelIdAndDateAndCateg(Integer channelId, Integer days, Integer servCategId, Integer categId) {
        log.info("listChannelOrderStockStatusByChannelIdAndDateAndCateg 参数为 channelId:{},days:{},servCategId:{},categID:{}", channelId, days, servCategId, categId);

        if (Objects.isNull(channelId) || Objects.isNull(servCategId) || Objects.isNull(categId) || Objects.isNull(days)) {
            return ResponseDTO.fromErrorCodeTable(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        if (Arrays.asList(ChannelConsts.ORDER_STOCK_SPECIAL_CHANNEL).contains(channelId)) {
            return ResponseDTO.success(Collections.emptyList());
        }

        // 超过30天只查30天的数据
        days = days > 30 ? 30 : days;
        final Integer paramDay = days;

        // 渠道是否开通分类，没开通取上级渠道id
        try {
            channelId = channelServiceCategoryBService.getAvailableCategoryChannelId(channelId);
        } catch (PlatException e) {
            return ResponseDTO.fromErrorCodeTable(e.getErrorCode());
        }

        List<ChannelConfigClose> channelConfigCloses = listByChannelConfigCloseQuery(channelId, paramDay, servCategId, categId);
        List<Date> dateList = channelConfigCloses.stream().map(ChannelConfigClose::getDay).collect(Collectors.toList());
        return ResponseDTO.success(dateList);
    }


    private List<ChannelConfigClose> listByChannelConfigCloseQuery(Integer channelId, Date date, Integer servCategId, Integer categId) {
        ChannelConfigCloseQuery query = new ChannelConfigCloseQuery();
        query.setChannelId(channelId);
        query.setServCategId(servCategId);
        query.setCategTwoId(categId);
        query.setStatus(1);
        query.setDay(date);
        List<ChannelConfigClose> channelConfigCloses = channelConfigCloseService.listByQuery(query);
        return channelConfigCloses;
    }

    private List<ChannelConfigClose> listByChannelConfigCloseQuery(Integer channelId, Integer days, Integer servCategId, Integer categId) {
        ChannelConfigCloseQuery query = new ChannelConfigCloseQuery();
        query.setStartDate(DateUtil.getDateStart(new Date()));
        query.setEndDate(DateUtil.getDateStart(DateUtil.getNowDefer(days)));
        query.setChannelId(channelId);
        query.setServCategId(servCategId);
        query.setCategTwoId(categId);
        query.setStatus(1);
        List<ChannelConfigClose> channelConfigCloses = channelConfigCloseService.listByQuery(query);
        return channelConfigCloses;
    }


}
